﻿// Copyright 2008 Rory Plaire (codekaizen@gmail.com)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using PerformanceDataRecorder;

namespace BubbleSortTest
{
    class Program
    {
        private static readonly Int32 MaxItems = 66537;
        private static readonly Int32 ItemCount = 2;
        private static readonly Int32 Rate = 2;
        private static readonly Random _random = new Random();
        private static readonly Recorder _recorder = new Recorder("log.xml");

        static void Main(string[] args)
        {
            Int32 items = ItemCount;
            while (items < MaxItems)
            {
                Console.WriteLine("Bubble sorting " + items + " integer items.");
                runIntegerTests(items);
                items *= Rate;
            }

            Console.WriteLine("");
            items = ItemCount;
            while (items < MaxItems)
            {
                Console.WriteLine("Bubble sorting " + items + " single float items.");
                runSingleTests(items);
                items *= Rate;
            }

            Console.WriteLine("");
            items = ItemCount;
            while (items < MaxItems)
            {
                Console.WriteLine("Bubble sorting " + items + " double float items.");
                runDoubleTests(items);
                items *= Rate;
            }

            Console.WriteLine("Done.");
            Console.ReadKey();
        }

        private static void runIntegerTests(Int32 itemCount)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            sortIntegerArray(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(Int32[]), typeof(Int32), itemCount,  timer.Elapsed);
            Console.WriteLine("\tSorting array: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortGenericIntegerList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(List<Int32>), typeof(Int32), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting generic list: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortObjectIntegerList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(ArrayList), typeof(Int32), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting object list: " + timer.ElapsedMilliseconds + " ms.");
        }

        private static void runSingleTests(Int32 itemCount)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            sortSingleArray(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(Single[]), typeof(Single), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting array: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortGenericSingleList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(List<Single>), typeof(Single), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting generic list: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortObjectSingleList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(ArrayList), typeof(Single), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting object list: " + timer.ElapsedMilliseconds + " ms.");
        }

        private static void runDoubleTests(Int32 itemCount)
        {
            Stopwatch timer = new Stopwatch();

            timer.Start();
            sortDoubleArray(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(Double[]), typeof(Double), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting array: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortGenericDoubleList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(List<Double>), typeof(Double), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting generic list: " + timer.ElapsedMilliseconds + " ms.");

            timer.Start();
            sortObjectDoubleList(itemCount);
            timer.Stop();
            _recorder.Log("Safe CLR", typeof(ArrayList), typeof(Double), itemCount, timer.Elapsed);
            Console.WriteLine("\tSorting object list: " + timer.ElapsedMilliseconds + " ms.");
        }

        private static void sortObjectIntegerList(Int32 itemCount)
        {
            ArrayList values = new ArrayList(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add(_random.Next());
            }

            sortIntegers(values);
        }

        private static void sortObjectSingleList(Int32 itemCount)
        {
            ArrayList values = new ArrayList(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add((Single)_random.NextDouble());
            }

            sortSingles(values);
        }

        private static void sortObjectDoubleList(Int32 itemCount)
        {
            ArrayList values = new ArrayList(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add(_random.NextDouble());
            }

            sortDoubles(values);
        }

        private static void sortGenericIntegerList(Int32 itemCount)
        {
            List<Int32> values = new List<Int32>(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add(_random.Next());
            }

            sortGenericIntegers(values);
        }

        private static void sortGenericSingleList(Int32 itemCount)
        {
            List<Single> values = new List<Single>(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add((Single)_random.NextDouble());
            }

            sortGenericSingles(values);
        }

        private static void sortGenericDoubleList(Int32 itemCount)
        {
            List<Double> values = new List<Double>(itemCount);

            for (Int32 i = 0; i < itemCount; i++)
            {
                values.Add(_random.NextDouble());
            }

            sortGenericDoubles(values);
        }

        private static void sortIntegerArray(Int32 itemCount)
        {
            Int32[] values = new Int32[itemCount];

            for (Int32 i = 0; i < itemCount; i++)
            {
                values[i] = _random.Next();
            }

            sortIntegers(values);
        }

        private static void sortSingleArray(Int32 itemCount)
        {
            Single[] values = new Single[itemCount];

            for (Int32 i = 0; i < itemCount; i++)
            {
                values[i] = (Single)_random.NextDouble();
            }

            sortSingles(values);
        }

        private static void sortDoubleArray(Int32 itemCount)
        {
            Double[] values = new Double[itemCount];

            for (Int32 i = 0; i < itemCount; i++)
            {
                values[i] = _random.NextDouble();
            }

            sortDoubles(values);
        }

        private static void sortIntegers(ArrayList values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Int32 v1 = (Int32)values[j];
                    Int32 v2 = (Int32)values[j + 1];
                    if (v1 > v2)
                    {
                        Int32 tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortSingles(ArrayList values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Single v1 = (Single)values[j];
                    Single v2 = (Single)values[j + 1];
                    if (v1 > v2)
                    {
                        Single tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortDoubles(ArrayList values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Double v1 = (Double)values[j];
                    Double v2 = (Double)values[j + 1];
                    if (v1 > v2)
                    {
                        Double tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortGenericIntegers(List<Int32> values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Int32 v1 = values[j];
                    Int32 v2 = values[j + 1];

                    if (v1 > v2)
                    {
                        Int32 tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortGenericSingles(List<Single> values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Single v1 = values[j];
                    Single v2 = values[j + 1];

                    if (v1 > v2)
                    {
                        Single tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortGenericDoubles(List<Double> values)
        {
            for (Int32 i = 0; i < values.Count; i++)
            {
                for (Int32 j = 0; j < values.Count - 1; j++)
                {
                    Double v1 = values[j];
                    Double v2 = values[j + 1];

                    if (v1 > v2)
                    {
                        Double tmp = v1;
                        values[j] = v2;
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortIntegers(Int32[] values)
        {
            for (Int32 i = 0; i < values.Length; i++)
            {
                for (Int32 j = 0; j < values.Length - 1; j++)
                {
                    if (values[j] > values[j + 1])
                    {
                        Int32 tmp = values[j];
                        values[j] = values[j + 1];
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortSingles(Single[] values)
        {
            for (Int32 i = 0; i < values.Length; i++)
            {
                for (Int32 j = 0; j < values.Length - 1; j++)
                {
                    if (values[j] > values[j + 1])
                    {
                        Single tmp = values[j];
                        values[j] = values[j + 1];
                        values[j + 1] = tmp;
                    }
                }
            }
        }

        private static void sortDoubles(Double[] values)
        {
            for (Int32 i = 0; i < values.Length; i++)
            {
                for (Int32 j = 0; j < values.Length - 1; j++)
                {
                    if (values[j] > values[j + 1])
                    {
                        Double tmp = values[j];
                        values[j] = values[j + 1];
                        values[j + 1] = tmp;
                    }
                }
            }
        }

    }
}
